package mdata

import (
	"fmt"
	"gitee.com/dennis-mxx/gcode-common/menv"
	"gitee.com/dennis-mxx/gcode-common/mexception"
	"gitee.com/dennis-mxx/gcode-common/mlogger"
	_ "github.com/go-sql-driver/mysql"
	"strings"
	"time"
	"xorm.io/xorm"
	"xorm.io/xorm/log"
)

var XormManager *xormManager

func InitMysql(logger *mlogger.TraceLogger, dataSource map[string]*menv.Mysql) {
	XormManager = NewXormManager()

	for id, meta := range dataSource {
		if meta.Addr == "" {
			panic(mexception.NewException(mexception.NilException, "mysql.addr is nil"))
		}

		if meta.MaxIdleConn == 0 {
			meta.MaxIdleConn = 5
		}
		if meta.MaxOpenConn == 0 {
			meta.MaxOpenConn = 600
		}
		if meta.Timeout == 0 {
			meta.Timeout = 30
		}
		var addr string
		if i := strings.Index(meta.Addr, "@"); i >= 0 {
			addr = "user:pass" + meta.Addr[i:]

		} else {
			addr = meta.Addr
		}
		if engine, err := ConnectionMysql(id, logger, meta); err == nil {
			XormManager.Register(id, engine)
			logger.Info(fmt.Sprintf("[mysql] [%s] connection successful", addr))
		} else {
			panic(fmt.Sprintf("[mysql] [%s] connection database failure ", addr))
		}
	}

}

func ConnectionMysql(id string, logger *mlogger.TraceLogger, dataSource *menv.Mysql) (*xorm.Engine, error) {
	defer mlogger.FormatException(func() *mlogger.TraceLogger {
		return logger
	})

	engine, err := xorm.NewEngine("mysql", dataSource.Addr)
	if err == nil {
		timeout := time.Duration(dataSource.Timeout)
		engine.SetMaxOpenConns(dataSource.MaxOpenConn)        // 用于设置最大打开的连接数，默认值为0表示不限制
		engine.SetMaxIdleConns(dataSource.MaxIdleConn)        // 用于设置闲置的连接数
		engine.SetConnMaxLifetime(timeout * time.Millisecond) // 设置一个超时时间，时间小于数据库的超时时间即可
		engine.SetLogger(NewXormLogger(id, logger))
		engine.ShowSQL(dataSource.ShowSql)
		engine.EnableSessionID(true)
		if menv.Environment.Logger != nil && menv.Environment.Logger.Level != "" {
			if strings.EqualFold(menv.Environment.Logger.Level, "warning") {
				engine.SetLogLevel(log.LOG_WARNING)
			} else if strings.EqualFold(menv.Environment.Logger.Level, "error") {
				engine.SetLogLevel(log.LOG_ERR)
			} else if strings.EqualFold(menv.Environment.Logger.Level, "debug") {
				engine.SetLogLevel(log.LOG_DEBUG)
			} else {
				engine.SetLogLevel(log.LOG_INFO)
			}

		}

	}

	return engine, err
}
